<template>
  <div>
    <PerfectTableComponent
      :loadTableList="loadTableList"
      :changePageSize="changePageSize"
      :changePage="changePage"
      :removeQueryField="removeQueryField"
      :clearQuery="clearQuery"
      v-model:query="query"
      title="账户"
      ref="tableRef"
      :queryFormHeaders="queryFormHeaders"
      :table="table"
      :tableColumns="tableColumns"
      :showTableIndex="false"
      :operatorColumnWidth="operatorColumnWidth"
      :baseUrl="urls.API_URL_BACKSTAGE_USER_MANAGE"
      :download-template-url="urls.API_URL_BACKSTAGE_USER_MANAGE_DOWNLOADTEMPLATE"
      :download-url="urls.API_URL_BACKSTAGE_USER_MANAGE_DOWNLOAD"
      templateFileName="账户导入模板"
      dataFileName="账户表导出记录"
      v-model:multipleSelection="multipleSelection"
      v-model:form="form"
      :formHeader="formHeader"
      @beforeSubmitQuery="beforeSubmitQuery"
      @beforeAddRow="beforeAddRow"
      @afterLoadDataSuccessInEditRow="afterLoadDataSuccessInEditRow"
      @beforeFormSubmit="beforeFormSubmit"
    >
      <!-----------------------------表格左侧工具栏的右侧----------------------------------------->
      <template #toorbar_left_right>
        <el-button
          :disabled="multipleSelection.length === 0"
          type="primary"
          style="margin: 0 5px 0 0"
          @click="batchOperatorRoles"
          >角色分配</el-button
        >
        <el-button
          :disabled="multipleSelection.length === 0"
          type="primary"
          style="margin: 0 5px 0 0"
          @click="transferDepartment"
          >部门转移</el-button
        >
      </template>
      <!-----------------------------表格查询表单自定义元素----------------------------------------->
      <template #query_form_departmentId>
        <SysDepartmentTreeSelect
          v-model="query['department.id']"
          @change="emit('changeDepartment', $event)"
          :data="departmentTree"
          :is-remote="false"
        />
      </template>
      <template #query_form_roles="scope: any">
        <el-select
          v-model="rolesSelect"
          value-key="id"
          multiple
          clearable
          :placeholder="`${scope.item.placeholder ? scope.item.placeholder : scope.item.label}`"
          style="width: 200px"
        >
          <el-option v-for="(item1, index1) in roles" :key="index1" :label="item1.nameZh" :value="item1.id"></el-option>
        </el-select>
      </template>
      <!-----------------------------表格自定义列----------------------------------------->
      <template #table_column_departmentName="scope: any">
        {{ scope.row.department != null ? scope.row.department.name : '' }}
      </template>
      <!--账户状态-->
      <template #table_column_status="scope: any">
        <el-tag :type="`${scope.row.status == 0 ? 'info' : scope.row.status == 1 ? 'success' : 'danger'}`"
          >{{ dictToMap(userStatusDict).get(scope.row.status) }}
        </el-tag>
      </template>
      <!--角色数量-->
      <template #table_column_roleNumber="scope: any">
        <el-popover v-if="scope.row.roles.length > 0" placement="right" :width="450" trigger="hover">
          <template #reference>
            <el-link type="primary">{{ scope.row.roleNumber }}</el-link>
          </template>
          <el-table :data="scope.row.roles">
            <el-table-column width="100" property="nameZh" label="角色中文名"></el-table-column>
            <el-table-column width="200" property="name" label="角色英文名"></el-table-column>
            <el-table-column width="50" property="level" label="级别"></el-table-column>
          </el-table>
        </el-popover>
        <template v-else> {{ scope.row.roleNumber }} </template>
      </template>
      <!-----------------------------表格自定义列（操作列）----------------------------------------->
      <template #table_operator_right="scope">
        <el-popconfirm
          v-if="showPermissionViewButton"
          width="200px"
          confirm-button-text="权限预览"
          cancel-button-text="菜单预览"
          confirmButtonType="default"
          cancelButtonType="default"
          title="请选择预览方式"
          icon="InfoFilled"
          @confirm="permissionView(scope.row.id)"
          @cancel="menuView(scope.row.id)"
        >
          <template #reference>
            <el-button type="primary" size="small" icon="Grid" plain>权限预览</el-button>
          </template>
        </el-popconfirm>
        <el-button
          v-if="showUploadPhotoButton"
          @click="uploadPhoto(scope.row.id)"
          type="primary"
          size="small"
          icon="User"
          plain
          >上传头像</el-button
        >
      </template>
      <!-----------------------------表单自定义元素----------------------------------------->
      <template #dialog_form_departmentId>
        <SysDepartmentTreeSelect v-model="form['departmentId']" :data="departmentTree" :is-remote="false" />
      </template>
      <template #dialog_form_roleIds>
        <!--角色列表-->
        <el-checkbox-group v-model="form['roleIds']">
          <el-checkbox
            v-for="item in roles"
            :label="item.nameZh"
            :value="item.id"
            :key="item.id"
            :disabled="!item.enabled"
          />
        </el-checkbox-group>
      </template>
    </PerfectTableComponent>
    <!-- 权限预览组件 -->
    <UserPermissionView ref="UserPermissionViewDialogRef" />
    <!-- 头像上传表单 -->
    <PhotoUploadDialog
      ref="photoUploadDialogRef"
      title="头像上传"
      :autoUpload="false"
      @uploadSuccess="uploadImgSuccess"
    />
    <!-- 角色批量分配对话库框组件 -->
    <UserRoleBatchOperationDialog ref="userRoleBatchOperationDialog" :roles="roles" :users="multipleSelection" />
    <!-- 角色批量分配对话库框组件 -->
    <UsersTransferDepartmentDialog
      ref="usersTransferDepartmentDialog"
      :departmentTree="departmentTree"
      :users="multipleSelection"
    />
  </div>
</template>

<script lang="ts" setup>
//导入完整表格组件
import PerfectTableComponent from '@/components/base/table/PerfectTableComponent.vue';
//导入权限预览组件
import UserPermissionView from '@/views/page/authority/usermanage/UserPermissionView.vue';
// 导入上传图像组件
import PhotoUploadDialog from '@/components/base/dialog/PhotoUploadDialogComponent.vue';
// 导入部门选择组件
import SysDepartmentTreeSelect from '@/components/auth/SysDepartmentTreeSelectComponent.vue';
//导入角色批量分配组件
import UserRoleBatchOperationDialog from '@/views/page/authority/usermanage/UserRoleBatchOperationDialogView.vue';
import UsersTransferDepartmentDialog from '@/views/page/authority/usermanage/UsersTransferDepartmentDialogView.vue';
import { onMounted, provide, ref, watch } from 'vue';
import useTableList from '@/api/hooks/useTableList';
import type { Department, Role, User } from '@/types/interface/auth_interface';
import urls from '@/api/request/urls';
import { userSexDict, userStatusDict, dictToMap, getDict } from '@/api/dict';
import { defineEmits } from 'vue';
import type { FormHeader, TableColumn, TreeData } from '@/types/interface/base_interface';
const emit = defineEmits(['changeDepartment']);
import Request from '@/api/request/request';

interface Props {
  // 需要在父组件引入自定义的@/api/uem/useTableList.ts组件，然后将其中的部分属性传过来
  showPermissionViewButton?: boolean; // 是否显示权限预览按钮
  showUploadPhotoButton?: boolean; // 是否显示上传按钮
  operatorColumnWidth?: number; // 表格操作列宽度
}
const props = withDefaults(defineProps<Props>(), {
  showPermissionViewButton: true,
  showUploadPhotoButton: true,
  operatorColumnWidth: 400
});

// 表格工具必备参数
const { table, query, loadTableList, removeQueryField, clearQuery, changePageSize, changePage } = useTableList(
  urls.API_URL_BACKSTAGE_USER_MANAGE
);
// 将表格刷新函数传到子容器
provide('loadTableList', loadTableList);

// 根据部门读取账户信息，主要暴露给父组件调用
const setDepartmentIdForQueryUser = (departmentId: number): void => {
  // 是否清空条件按实际需求决定，目前决定是不清空
  // clearQuery();
  query.value['department.id'] = departmentId; // 加上部门查询条件
  loadTableList();
};

// 当修改treeselect中的部门信息时
// const changeDepartment = (departmentId: string) => {
//   emit('changeTreeSelectDepartment', departmentId);
// };

//查询==========================================================
const queryFormHeaders = ref<FormHeader[]>([]);
//角色选择下拉框组件====================
const rolesSelect = ref<Role[]>([]);
//查询对话框提交前的回调。需要额外封装参数时调用
const beforeSubmitQuery = (queryForm: any) => {
  query.value.roleIds = rolesSelect.value.toString();
};
//建立双向绑定，即角色下拉框查询条件清空时另一个变量也清空
watch(
  () => query.value.roleIds,
  (newVal: any, oldVal: any) => {
    if ((typeof newVal === 'undefined' || newVal === '') && oldVal !== '') {
      // 如果当前值不存在并且上一个值不为空，则说明日期被清空了
      rolesSelect.value = [];
    }
  }
);
//表格==========================================================
// 表格插件ref对象
const tableRef = ref();

//表格列
// 定义表格所有的列字段信息
const tableColumns = ref<TableColumn[]>([]);
//定义表格复选框。注意非必填字段
const multipleSelection = ref<Role[]>([]); // 复选框选择的记录row
//表单==========================================================
//表单对象
const form = ref<User>({});
//表单元素类型
const formHeader = ref<FormHeader[]>([]);

// 添加编辑对话框中的角色复选框组件================================
// 读取角色列表
const roles = ref<Role[]>([]); // 定义角色列表
const initRoles = async () => {
  const resData: any = await new Request(urls.API_URL_BACKSTAGE_ROLE_MANAGE_ALL).get();
  if (resData.success) {
    roles.value = resData.data;
  }
};

//供一些异步交互的在这里初始化
onMounted(async () => {
  // 初始化角色列表复选框
  await initRoles();
  //定义性别选项。放在mounted中执行时，要将引用改变量的属性也放进来。
  const sexDict = await getDict('用户性别', 'number');
  //表格列加载
  queryFormHeaders.value = [
    // 查询表单
    {
      prop: 'username',
      label: '账号',
      placeholder: '请输入账户名'
    },
    {
      prop: 'nickName',
      label: '网名'
    },
    {
      prop: 'sex',
      label: '性别',
      placeholder: '请选择性别',
      type: 'select',
      list: sexDict,
      show: false
    },
    {
      prop: 'status',
      label: '用户状态',
      placeholder: '请选择用户状态',
      type: 'select',
      list: userStatusDict,
      show: false
    },
    {
      prop: 'departmentId',
      propAsName: 'department.id',
      label: '部门',
      placeholder: '请选择部门',
      type: 'custom',
      show: false
    },
    {
      prop: 'roles',
      propAsName: 'roleIds',
      label: '角色',
      placeholder: '请选择角色',
      type: 'custom',
      show: false
    },
    {
      prop: 'createTimeQueryBetween',
      propAsNames: ['createTimeQueryOfBegin', 'createTimeQueryOfEnd'],
      label: '注册时间',
      type: 'daterange',
      show: false,
      width: '300px'
    }
  ];

  tableColumns.value = [
    {
      label: '头像',
      prop: 'headImgUrl',
      fixed: true,
      type: 'image',
      width: 100
    },
    {
      label: '账户名',
      prop: 'username',
      fixed: true,
      width: 150
    },
    {
      label: '部门名称',
      prop: 'departmentName', // department.name关联属性不能直接传到自定义表格插件显示，需要使用自定义方式来显示
      width: 150,
      type: 'custom'
    },
    {
      label: '姓名',
      prop: 'nickName',
      width: 150
    },
    {
      label: '性别',
      prop: 'sex',
      width: 60,
      type: 'dict',
      dict: sexDict
    },
    {
      label: '状态',
      prop: 'status',
      width: 100,
      type: 'custom'
    },
    {
      label: '角色数量',
      prop: 'roleNumber',
      width: 90,
      type: 'custom'
    },
    {
      label: '权限数量',
      prop: 'permissionNumber',
      width: 90
    },
    {
      label: '创建时间',
      prop: 'createTime',
      width: 180
    }
  ];
  //这里要将formHeader放在此处赋值。因为setup执行优先级最高，如果放在外面，会因为还没有生成sexDict报错
  formHeader.value = [
    {
      label: '部门',
      prop: 'departmentId',
      // propAsName: 'department.id',
      type: 'custom',
      rules: [
        {
          required: true,
          message: '不能为空',
          trigger: 'blur'
        }
      ]
    },
    {
      label: '账户名',
      prop: 'username',
      rules: [
        {
          required: true,
          message: '不能为空',
          trigger: 'blur'
        },
        {
          min: 4,
          max: 20,
          message: '长度在 4 到 20个字符',
          trigger: 'blur'
        }
      ]
    },
    {
      label: '昵称',
      prop: 'nickName',
      rules: [
        {
          required: true,
          message: '不能为空',
          trigger: 'blur'
        },
        {
          min: 2,
          max: 20,
          message: '长度在 2 到 20个字符',
          trigger: 'blur'
        }
      ]
    },
    {
      label: '性别',
      prop: 'sex',
      type: 'select',
      list: sexDict
    },
    {
      label: '账户状态',
      prop: 'status',
      type: 'select',
      list: userStatusDict
    },
    {
      label: '描述',
      prop: 'description',
      placeholder: '请输入账户的描述',
      type: 'textarea'
    },
    {
      label: '角色',
      prop: 'roleIds',
      type: 'custom',
      rules: [
        {
          type: 'array',
          required: true,
          message: '请至少选择一个角色',
          trigger: 'change'
        }
      ]
    }
  ];
});
//在添加行的动作以前
const beforeAddRow = async () => {
  //传入初始值
  form.value = {
    sex: 0,
    status: 1,
    roleIds: []
  };
  //将默认角色添加上去
  roles.value.forEach((role: Role) => {
    if (role.defaultRole === true) {
      // 如果是默认角色
      (form.value!.roleIds as number[]).push(role.id!); // 让复选框开始就选择默认角色
    }
  });
};

//在编辑行的动作成功以后
const afterLoadDataSuccessInEditRow = async (formEdit: User) => {
  //重新封装表单对象的值
  if (formEdit.department != null) {
    formEdit.departmentId = formEdit.department.id;
  }
  //遍历后端传递过来已经拥有的账户角色,将其封装给roleIds
  form.value.roleIds = [];
  if (form.value.roles != null) {
    form.value.roles.forEach((role: Role) => {
      form.value.roleIds!.push(role.id!); // 让复选框开始就选择该账户已经拥有的角色
    });
  }
};
//在表单提交前对对象进行封装
const beforeFormSubmit = () => {
  // 钩子函数，提交表单前的操作
  form.value!.department = {
    // 创建部门对象
    id: form.value!.departmentId as number
  };
};
//权限预览组件================================
const UserPermissionViewDialogRef = ref();
const permissionView = (userId: number) => {
  UserPermissionViewDialogRef.value.openDialog(userId, false);
};

const menuView = (userId: number) => {
  UserPermissionViewDialogRef.value.openDialog(userId, true);
};
// 头像上传组件================================
const photoUploadDialogRef = ref();
// 当点击头像上传按钮时
const uploadPhoto = (userId: number) => {
  // 设置头像上传地址
  let uploadImgUrl = urls.API_URL_BACKSTAGE_USER_UPLOAD_PHOTO.replace('{userId}', userId.toString());
  photoUploadDialogRef.value.openDialog(uploadImgUrl);
};
// 当头像上传成功
const uploadImgSuccess = () => {
  // 重新加载表格
  loadTableList();
};
//角色批量分配
const userRoleBatchOperationDialog = ref();
const batchOperatorRoles = () => {
  //选择了记录才打开窗口
  if (multipleSelection.value.length > 0) {
    userRoleBatchOperationDialog.value.openDialog(); //打开相应窗口
  }
};

//获取部门信息，传递到子组件，避免多个子组件都分别从服务端读取。
const departmentTree = ref<TreeData[]>([]);
onMounted(async () => {
  // 读取部门树形菜单
  const resData: any = await new Request(urls.API_URL_BACKSTAGE_DEPARTMENT_TREE).get();
  if (resData.success) {
    departmentTree.value = resData.data;
  }
});
//部门批量转移
const usersTransferDepartmentDialog = ref();
const transferDepartment = () => {
  usersTransferDepartmentDialog.value.openDialog();
};

defineExpose({
  setDepartmentIdForQueryUser
});
</script>
<style lang="scss" scoped></style>
